package com.zl.common.convert;

import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;

import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.XmlUtil;


public class StringConverterWithZone extends AbstractConverter<String> {
    private static final long serialVersionUID = 1L;

    private final Class<?> targetType;
    /**
     * 日期格式化
     */
    private String format;
    private String zoneIdStr;
    /**
     * 构造
     *
     * @param targetType 目标类型
     */
    public StringConverterWithZone(Class<?> targetType,String zoneIdStr) {
        this(targetType, null,zoneIdStr);
    }

    /**
     * 构造
     *
     * @param targetType 目标类型
     * @param format     日期格式
     */
    public StringConverterWithZone(Class<?> targetType, String format,String zoneIdStr) {
        this.targetType = targetType;
        this.format = format;
        this.zoneIdStr = zoneIdStr;
    }
    
    @Override
    protected String convertInternal(Object value) {
        if (value instanceof TimeZone) {
            return ((TimeZone) value).getID();
        } else if (value instanceof org.w3c.dom.Node) {
            return XmlUtil.toStr((org.w3c.dom.Node) value);
        } else if (value instanceof Clob) {
            return clobToStr((Clob) value);
        } else if (value instanceof Blob) {
            return blobToStr((Blob) value);
        } else if (value instanceof Type) {
            return ((Type) value).getTypeName();
        }else if (value instanceof Instant && zoneIdStr!=null) {
            return DateTimeFormatter.ofPattern(this.format)//.withLocale(Locale.SIMPLIFIED_CHINESE)
                    .withZone(ZoneId.of(this.zoneIdStr))
                    .format((Instant) value);
        }else if (value instanceof LocalDateTime && zoneIdStr!=null) {
            return DateTimeFormatter.ofPattern(this.format)//.withLocale(Locale.SIMPLIFIED_CHINESE)
                    .withZone(ZoneId.of(this.zoneIdStr))
                    .format((LocalDateTime) value);
        }else if (value instanceof Date) {
            SimpleDateFormat sdf = new SimpleDateFormat(this.format);
            return sdf.format((Date) value);
        }else if (value instanceof byte[]) {
            return new String((byte[]) value,Charset.defaultCharset());
        }

        // 其它情况
        return convertToStr(value);
    }

    /**
     * Clob字段值转字符串
     *
     * @param clob {@link Clob}
     * @return 字符串
     * @since 5.4.5
     */
    private static String clobToStr(Clob clob) {
        Reader reader = null;
        try {
            reader = clob.getCharacterStream();
            return IoUtil.read(reader);
        } catch (SQLException e) {
            throw new ConvertException(e);
        } finally {
            IoUtil.close(reader);
        }
    }

    /**
     * Blob字段值转字符串
     *
     * @param blob    {@link Blob}
     * @return 字符串
     * @since 5.4.5
     */
    private static String blobToStr(Blob blob) {
        InputStream in = null;
        try {
            in = blob.getBinaryStream();
            return IoUtil.read(in, CharsetUtil.CHARSET_UTF_8);
        } catch (SQLException e) {
            throw new ConvertException(e);
        } finally {
            IoUtil.close(in);
        }
    }
}
